package com.habdqn.studentmanager.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.github.pagehelper.PageInfo;
import com.github.xiaofan1519.verify.core.Verify;
import com.github.xiaofan1519.verify.exception.VerifyException;
import com.habdqn.studentmanager.bean.AttendanceMachine;
import com.habdqn.studentmanager.bean.AttendanceRecord;
import com.habdqn.studentmanager.bean.AttendanceSetting;
import com.habdqn.studentmanager.bean.Product;
import com.habdqn.studentmanager.bean.StudentAttRecord;
import com.habdqn.studentmanager.bean.ajax.Page;
import com.habdqn.studentmanager.bean.ajax.Request;
import com.habdqn.studentmanager.bean.ajax.Response;
import com.habdqn.studentmanager.constant.Constant;
import com.habdqn.studentmanager.constant.ErrorCode;
import com.habdqn.studentmanager.exception.StudentException;
import com.habdqn.studentmanager.service.AttendanceService;
import com.habdqn.studentmanager.service.ProductService;
import com.habdqn.studentmanager.util.AttendanceConnectionManager;
import com.habdqn.studentmanager.util.DateUtil;

/**
 * @author Fan
 * 
 *         2017年7月6日
 * 
 */
@Controller
@RequestMapping("/attendance")
public class AttendanceController extends BaseController {

    @Resource
    private ProductService productService;

    @Resource
    private AttendanceService attService;

    @RequestMapping("/list")
    public String list(StudentAttRecord bean, @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, Model model) {

        try {
            // 默认取当天时间
            if (null == bean) {
                bean = new StudentAttRecord();
            }

            if (null == bean.getAttDate()) {
                bean.setAttDate(new Date());
            }

            PageInfo<Product> products = productService.findProductList(null, null, null);
            PageInfo<StudentAttRecord> records = attService.findStudentRecordList(bean, pageNum, pageSize);

            addAttr(model, "products", products.getList());
            addAttr(model, "bean", bean);
            addAttr(model, "pageInfo", records);
        }
        catch (StudentException e) {
            return setErrMsg(model, e);
        }

        return "attendance/list";
    }

    /**
     * 跳转到指导页面
     * 
     * @return
     */
    @RequestMapping("/guide")
    public String toGuide() {

        return "attendance/guide";
    }

    /**
     * 跳转到排班界面
     * 
     * @return
     */
    @RequestMapping("/setting")
    public String toSetting(Model model) {

        try {
            AttendanceSetting setting = attService.getSetting();

            addAttr(model, "setting", setting);
        }
        catch (StudentException e) {
            return setErrMsg(model, e);
        }

        return "attendance/setting";
    }

    /**
     * 更新排班配置
     * 
     * @return
     */
    @RequestMapping(value = "/setting", method = RequestMethod.POST)
    @ResponseBody
    public Response setting(AttendanceSetting bean, Model model) {

        try {
            Verify.verifyNull(bean);
            Verify.verifyNull(bean.getOnWork());
            Verify.verifyNull(bean.getOffWork());
            Verify.verifyNull(bean.getAllowLate());
            Verify.verifyNull(bean.getAllowLeave());

            attService.updateSetting(bean);
            return buildRsp();
        }
        catch (VerifyException e) {
            logger.debug("参数非法", e);
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e.getMessage());
        }
    }

    /**
     * 跳转至补考勤页面
     * 
     * @return
     */
    @RequestMapping(value = "/remedy", method = RequestMethod.GET)
    public String toRemedy() {

        return "attendance/remedy";
    }

    /**
     * 补考勤记录
     * @param bean
     * @return
     */
    @RequestMapping(value = "/remedy", method = RequestMethod.POST)
    @ResponseBody
    public Response remedy(AttendanceRecord bean) {

        try {
            validate(bean);
            attService.addRecord(bean, false);

            return buildRsp();
        }
        catch (VerifyException e) {
            logger.debug("参数非法", e);
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e.getMessage());
        }
    }

    /**
     * 批量导入考勤记录
     * @param file
     * @param model
     * @return
     */
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    @ResponseBody
    public Response importRecord(@RequestParam("file") CommonsMultipartFile file, Model model) {

        try {
            InputStream is = file.getInputStream();
            attService.importRecord(is);
            return buildRsp();
        }
        catch (StudentException e) {
            logger.debug("系统异常", e);
            return buildRsp(ErrorCode.System_Error, e.getMessage());
        }
        catch (RuntimeException e) {
            logger.error("系统异常", e);
            return buildRsp(ErrorCode.System_Error, "系统异常");
        }
        catch (IOException e) {
            logger.error("打开上传文件失败", e);
            return buildRsp(ErrorCode.System_Error, "打开上传文件失败");
        }
    }

    /**
     * 校验参数
     * 
     * @param bean
     */
    public static void validate(AttendanceRecord bean) {
        Verify.verifyNull(bean);
        Verify.verifyNull(bean.getStudent());
        Verify.verifyNull(bean.getStudent().getId());
        Verify.verifyNull(bean.getAttDate());
    }

    /**
     * 查询考勤机列表
     * 
     * @param request
     * @return
     */
    @RequestMapping("/machine")
    public String toMachine() {

        return "attendance/machine";
    }

    /**
     * 查询考勤机列表
     * 
     * @param request
     * @return
     */
    @RequestMapping(value = "/machine/list", method = RequestMethod.POST)
    @ResponseBody
    public Response machineList(@RequestBody Request<AttendanceMachine> request) {
        
        try {
            AttendanceMachine machine = request.getCondition();
            Page page = request.getPage();
            if (null == page) {
                page = new Page();
            }
            
            PageInfo<AttendanceMachine> pageInfo = attService.findMachineList(machine, page);
            return buildRsp(pageInfo);
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    @RequestMapping(value = "/machine/{id}/info", method = RequestMethod.GET)
    @ResponseBody
    public Response machineInfo(@PathVariable Integer id) {

        try {
            Verify.verifyNull(id);
            AttendanceMachine bean = new AttendanceMachine();
            bean.setId(id);
            bean = attService.getMachine(bean);
            return buildRsp(bean);
        }
        catch (VerifyException e) {
            logger.debug("参数非法", e);
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    @RequestMapping(value = "/machine/{id}/del", method = RequestMethod.GET)
    @ResponseBody
    public Response machineDel(@PathVariable Integer id) {

        try {
            Verify.verifyNull(id);
            AttendanceMachine bean = new AttendanceMachine();
            bean.setId(id);
            attService.deleteMachine(bean);
            return buildRsp(bean);
        }
        catch (VerifyException e) {
            logger.debug("参数非法", e);
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    /**
     * 新增考勤机
     * 
     * @param bean
     * @return
     */
    @RequestMapping(value = "/machine/add", method = RequestMethod.POST)
    @ResponseBody
    public Response machineAdd(AttendanceMachine bean) {

        try {
            Verify.verifyNull(bean);
            Verify.verifyNull(bean.getName());
            Verify.verifyNull(bean.getAddress());
            validateIp(bean.getAddress());

            attService.addMachine(bean);
            return buildRsp();
        }
        catch (VerifyException e) {
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    /**
     * 编辑考勤机
     * 
     * @param bean
     * @return
     */
    @RequestMapping(value = "/machine/edit", method = RequestMethod.POST)
    @ResponseBody
    public Response machineEdit(AttendanceMachine bean) {

        try {
            Verify.verifyNull(bean);
            Verify.verifyNull(bean.getId());
            Verify.verifyNull(bean.getName());
            Verify.verifyNull(bean.getAddress());
            validateIp(bean.getAddress());

            attService.updateMachine(bean);
            return buildRsp();
        }
        catch (VerifyException e) {
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    /**
     * 连接考勤机
     * 
     * @param bean
     * @return
     */
    @RequestMapping(value = "/machine/connec", method = RequestMethod.POST)
    @ResponseBody
    public Response machineConnec(Integer id) {

        try {
            Verify.verifyNull(id);
            AttendanceMachine bean = new AttendanceMachine();
            bean.setId(id);
            bean = attService.getMachine(bean);
            AttendanceConnectionManager.remove(bean.getId());
            AttendanceConnectionManager.add(bean);
            return buildRsp();
        }
        catch (VerifyException e) {
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    /**
     * 停止与考勤机的连接
     * 
     * @param bean
     * @return
     */
    @RequestMapping(value = "/machine/stop", method = RequestMethod.POST)
    @ResponseBody
    public Response machineStop(Integer id) {

        try {
            Verify.verifyNull(id);
            AttendanceConnectionManager.remove(id);
            return buildRsp();
        }
        catch (VerifyException e) {
            return buildRsp(ErrorCode.Invalid_Argument, "参数非法");
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }

    /**
     * 校验ip
     * 
     * @param ipStr
     */
    private void validateIp(String ipStr) {
        String[] tmp = ipStr.split(":");
        if (tmp.length != 2) {
            throw new StudentException("ip校验失败");
        }

        String ip = tmp[0];
        String[] nums = ip.split("\\.");

        if (nums.length != 4) {
            throw new StudentException("ip校验失败");
        }

        try {
            // 校验ip
            for (int i = 0; i < nums.length; i++) {
                Integer num = Integer.valueOf(nums[i]);

                if (num < 0 || num >= 255) {
                    throw new StudentException("ip校验失败");
                }
            }

            // 校验端口
            Integer port = Integer.valueOf(tmp[1]);

            if (port <= 0 || port > 65535) {
                throw new StudentException("端口校验失败");
            }
        }
        catch (NumberFormatException e) {
            throw new StudentException("ip校验失败");
        }
    }

    /**
     * 根据筛选条件导出学生数据
     * 
     * @param student
     * @param rsp
     * @param model
     * @return
     */
    @RequestMapping("/export")
    public String export(StudentAttRecord bean, HttpServletResponse rsp, Model model) {

        Date date = bean.getAttDate();
        String fileName = DateUtil.format(date, DateUtil.FormatStr14) + "-attendance.xlsx";
        try {
            OutputStream out = rsp.getOutputStream();
            // 设置强制下载不打开
            rsp.setContentType("application/force-download");
            // 设置文件名
            rsp.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            attService.export(bean, out);
        }
        catch (StudentException e) {
            setErrMsg(model, e.getMessage());
            return Constant.ERROR_PAGE;
        }
        catch (IOException e) {
            logger.error("请求异常", e);
            setErrMsg(model, "请求异常");
            return Constant.ERROR_PAGE;
        }

        return null;
    }
}